#include "StdAfx.h"
#include "io_service_pool.h"
#include <boost/thread/thread.hpp>
namespace fly {

	namespace jld{

		namespace pool
		{

			//intial io_service and work , the work can stop calling io_service::run,
			//even if the io_service without any task in execution. 
			io_service_pool::io_service_pool(size_t size)
				:next_io_service_(0)
			{
				cout<<"initialize io service pool"<<endl;
				if (size == 0)
				{
					cerr<<"The io_service_pool size is zero."<<endl;
				}

				for (std::size_t i = 0; i < size; ++i)
				{
					io_service_ptr io_service(new boost::asio::io_service);
					work_ptr work(new boost::asio::io_service::work(*io_service));
					io_services_.push_back(io_service);
					works_.push_back(work);
				}
			}

			io_service_pool::~io_service_pool()
			{
				stop();
			}

			//creat a thread for each io_service and put them into threads.lastly,run them. 
			void io_service_pool::run()
			{
				// Create a pool of threads to run all of the io_services.
				std::vector<boost::shared_ptr<boost::thread> > threads;
				for (std::size_t i = 0; i < io_services_.size(); ++i)
				{
					boost::shared_ptr<boost::thread> thread(new boost::thread(
						boost::bind(&boost::asio::io_service::run, io_services_[i])));
					threads.push_back(thread);
				}

				// Wait for all threads in the pool to exit.
				for (std::size_t i = 0; i < threads.size(); ++i)
				{
					threads[i]->join();
				}
			}

			void io_service_pool::stop()
			{
				// Explicitly stop all io_services.
				for (std::size_t i = 0; i < io_services_.size(); ++i)
				{
					io_services_[i]->stop();
				}
			}

			//turn to take io_service one by one from io_services_. 
			boost::asio::io_service& io_service_pool::get_io_service()
			{
				// Use a round-robin scheme to choose the next io_service to use.
				boost::asio::io_service& io_service = *io_services_[next_io_service_];
				++next_io_service_;
				if (next_io_service_ == io_services_.size())
				{
					next_io_service_ = 0;
				}
				return io_service;
			}

		}
	}
}